package com.btcode.web.freemarker.servlet;

import com.btcode.common.MyLog;
import com.btcode.exception.MsgException;
import com.btcode.log.ILog;
import com.btcode.web.core.errorhandle.IErrorHandler;
import com.btcode.web.freemarker.errorhandle.DefaultFreeMarkerErrorHandler;
import freemarker.cache.MruCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * freemarker处理器
 *
 * @author gislin
 */
public class FreemarkerHandleServlet implements Servlet {

    private ILog log;
    private Configuration cfg;
    private String freemarkerBasePath;
    private boolean useCache;

    /**
     * 项目的根地址，相当于项目名
     */
    private String contextPath;

    private IErrorHandler errorHandler;

    public FreemarkerHandleServlet(String freemarkerBasePath, boolean useCache) {
        this.freemarkerBasePath = freemarkerBasePath;
        log = MyLog.getInstance().getLogger(FreemarkerHandleServlet.class.getName());
        this.useCache = useCache;
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }

    public void setErrorHandler(IErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    @Override
    public void init(ServletConfig arg0) throws ServletException {

        try {
            cfg = new Configuration(Configuration.VERSION_2_3_27);
            cfg.setDirectoryForTemplateLoading(new File(freemarkerBasePath));
            cfg.setDefaultEncoding("UTF-8");
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            cfg.setLogTemplateExceptions(false);
            cfg.setWrapUncheckedExceptions(true);
            /**
             * 设置缓存
             */
            if (useCache) {
                cfg.setCacheStorage(new MruCacheStorage(20, 250));
                cfg.setTemplateUpdateDelayMilliseconds(60000);
            }

            contextPath = arg0.getServletContext().getContextPath();
        }
        catch (Exception e) {
            throw new MsgException("初始化freemarker失败", e);
        }

    }

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
        throws ServletException, IOException {

        try {
            HttpServletRequest request = (HttpServletRequest) arg0;
            String requestPath = request.getRequestURI();
            /**
             * 把项目地址去掉，项目地址是自定义的，并不真正包含在物理路径里
             */
            requestPath = requestPath.replaceFirst(contextPath, "");

            Template temp = cfg.getTemplate(requestPath);
            Map<String, Object> root = new HashMap<>();
            root.put("contextPath", contextPath);

            Writer out = arg1.getWriter();
            temp.process(root, out);
        }
        catch (Exception e) {
            log.error("页面请求错误", e);
            if (errorHandler == null) {
                errorHandler = new DefaultFreeMarkerErrorHandler();
            }
            errorHandler.handleError(arg0, arg1, e);
        }
    }

}
